#if !NUNIT
using Microsoft.VisualStudio.TestTools.UnitTesting;
#else
using NUnit.Framework;
using TestClass = NUnit.Framework.TestFixtureAttribute;
using TestInitialize = NUnit.Framework.SetUpAttribute;
using TestCleanup = NUnit.Framework.TearDownAttribute;
using TestMethod = NUnit.Framework.TestAttribute;
#endif

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Validation.Tests.TestClasses;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

namespace Microsoft.Practices.EnterpriseLibrary.Validation.Tests
{
	[TestClass]
	public class PropertyValidationFixture
	{
		[ExpectedException(typeof(ArgumentNullException))]
		[TestMethod]
		public void ShouldThrowIfValidateNullTarget()
		{
			ValidationResults results = PropertyValidation.Validate<TestObjectWithFailingAttributesOnProperties>(
				null,
				typeof(TestObjectWithFailingAttributesOnProperties).GetProperty("FailingProperty1"),
				new object());
		}

		[ExpectedException(typeof(ArgumentNullException))]
		[TestMethod]
		public void ShouldThrowIfValidateNullProperty()
		{
			ValidationResults results = PropertyValidation.Validate(
				new TestObjectWithFailingAttributesOnProperties(),
				null,
				new object());
		}

		[ExpectedException(typeof(ArgumentNullException))]
		[TestMethod]
		public void ShouldThrowIfValidateNullRuleset()
		{
			ValidationResults results = PropertyValidation.Validate(
				new TestObjectWithFailingAttributesOnProperties(),
				typeof(TestObjectWithFailingAttributesOnProperties).GetProperty("_NonExistingProp"),
				new object());
		}

		[TestMethod]
		public void CanValidatePropertyWithoutRuleset()
		{
			ValidationResults results = PropertyValidation.Validate(
				new TestObjectWithFailingAttributesOnProperties(),
				typeof(TestObjectWithFailingAttributesOnProperties).GetProperty("FailingProperty1"),
				new object());

			Assert.IsFalse(results.IsValid);
			IList<ValidationResult> resultsList = ValidationTestHelper.GetResultsList(results);
			Assert.AreEqual(1, resultsList.Count);
			Assert.AreEqual("message1", resultsList[0].Message);
		}

		[TestMethod]
		public void CanValidatePropertyWithRuleSet()
		{
			ValidationResults results = PropertyValidation.Validate(
				new TestObjectWithFailingAttributesOnProperties(),
				typeof(TestObjectWithFailingAttributesOnProperties).GetProperty("FailingProperty1"),
				new object(),
				"RuleA");

			Assert.IsFalse(results.IsValid);
			IList<ValidationResult> resultsList = ValidationTestHelper.GetResultsList(results);
			Assert.AreEqual(1, resultsList.Count);
			Assert.AreEqual("message1-RuleA", resultsList[0].Message);
		}

		[TestMethod]
		public void CanValidatePropertyWithCrossReference()
		{
			TestObjectWithCrossProperty obj = new TestObjectWithCrossProperty();

			ValidationResults results = PropertyValidation.Validate(
				obj,
				typeof(TestObjectWithCrossProperty).GetProperty("Property1"),
				-5);

			Assert.IsFalse(results.IsValid);


			results = PropertyValidation.Validate(
				obj,
				typeof(TestObjectWithCrossProperty).GetProperty("Property1"),
				10);

			Assert.IsTrue(results.IsValid);
		}

		[TestMethod]
		public void CanGetValidatorForProperty()
		{
			bool called = false;

			Validator validator = PropertyValidation.GetValidator<TestObjectWithFailingAttributesOnProperties>(
				typeof(TestObjectWithFailingAttributesOnProperties).GetProperty("FailingProperty1"),
				delegate { called = true; return new object(); });

			ValidationResults results = validator.Validate(new TestObjectWithFailingAttributesOnProperties());

			Assert.IsTrue(called);
			Assert.IsFalse(results.IsValid);
			IList<ValidationResult> resultsList = ValidationTestHelper.GetResultsList(results);
			Assert.AreEqual(1, resultsList.Count);
			Assert.AreEqual("message1", resultsList[0].Message);
		}

		[TestMethod]
		public void CanGetValidatorForPropertyAndRuleset()
		{
			bool called = false;

			Validator validator = PropertyValidation.GetValidator<TestObjectWithFailingAttributesOnProperties>(
				typeof(TestObjectWithFailingAttributesOnProperties).GetProperty("FailingProperty1"),
				delegate { called = true; return new object(); },
				"RuleA");

			ValidationResults results = validator.Validate(new TestObjectWithFailingAttributesOnProperties());

			Assert.IsTrue(called);
			Assert.IsFalse(results.IsValid);
			IList<ValidationResult> resultsList = ValidationTestHelper.GetResultsList(results);
			Assert.AreEqual(1, resultsList.Count);
			Assert.AreEqual("message1-RuleA", resultsList[0].Message);
		}

		[ExpectedException(typeof(ArgumentNullException))]
		[TestMethod]
		public void ShouldThrowIfGetValidatorNullOwner()
		{
			Validator validator = PropertyValidation.GetValidator(
				null,
				typeof(TestObjectWithFailingAttributesOnProperties).GetProperty("FailingProperty1"),
				delegate { return new object(); },
				"RuleA");
		}

		[ExpectedException(typeof(ArgumentNullException))]
		[TestMethod]
		public void ShouldThrowGetValidatorNullProperty()
		{
			Validator validator = PropertyValidation.GetValidator(
				typeof(TestObjectWithFailingAttributesOnProperties),
				null,
				delegate { return new object(); },
				"RuleA");
		}

		[ExpectedException(typeof(ArgumentNullException))]
		[TestMethod]
		public void ShouldThrowIfGetValidatorNullValueGetter()
		{
			Validator validator = PropertyValidation.GetValidator(
				typeof(TestObjectWithFailingAttributesOnProperties),
				typeof(TestObjectWithFailingAttributesOnProperties).GetProperty("FailingProperty1"),
				null,
				"RuleA");
		}

		[ExpectedException(typeof(ArgumentNullException))]
		[TestMethod]
		public void ShouldThrowIfGetValidatorNullRuleset()
		{
			Validator validator = PropertyValidation.GetValidator(
				typeof(TestObjectWithFailingAttributesOnProperties),
				typeof(TestObjectWithFailingAttributesOnProperties).GetProperty("FailingProperty1"),
				delegate { return new object(); },
				null);
		}

		class TestObjectWithCrossProperty
		{
			private int prop1;

			[PropertyComparisonValidator("Property2", ComparisonOperator.GreaterThan)]
			public int Property1
			{
				get { return prop1; }
				set { prop1 = value; }
			}

			private int prop2;

			public int Property2
			{
				get { return prop2; }
				set { prop2 = value; }
			}

		}
	}
}
